//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.

#include <osg/ColorMask>
#include <osg/Viewport>

#include <osgUtil/RenderBin>
#include <osgUtil/RenderStageLighting>

/**
 * RenderState base class. Used for encapsulate a complete stage in
 * rendering - setting up of viewport, the projection and model
 * matrices and rendering the RenderBin's enclosed with this RenderStage.
 * RenderStage also has a dependency list of other RenderStages, each
 * of which must be called before the rendering of this stage.  These
 * 'pre' rendering stages are used for advanced rendering techniques
 * like multistage pixel shading or impostors.
 */
class RenderStage : public RenderBin
{
    public:
    

        RenderStage();
        virtual osg::Object* cloneType() const { return new RenderStage(); }
        virtual osg::Object* clone(const osg::CopyOp&) const { return new RenderStage(); } // note only implements a clone of type.
        virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const RenderStage*>(obj)!=0L; }
        virtual const char* className() const { return "RenderStage"; }

        virtual void reset();
        
        
        /** Set the viewport.*/
        void setViewport(osg::Viewport* viewport) { _viewport = viewport; }

        /** Get the const viewport. */
        const osg::Viewport* getViewport() const { return _viewport.get(); }

        /** Get the viewport. */
        osg::Viewport* getViewport() { return _viewport.get(); }



        /** Set the clear mask used in glClear(..).
          * Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */
        void setClearMask(const GLbitfield mask) { _clearMask = mask; }

        /** Get the clear mask.*/
        const GLbitfield getClearMask() const { return _clearMask; }


        void setColorMask(osg::ColorMask* cm) { _colorMask = cm; }
        osg::ColorMask* getColorMask() { return _colorMask.get(); }
        const osg::ColorMask* getColorMask() const { return _colorMask.get(); }


        /** Set the clear color used in glClearColor(..). 
          * glClearColor is only called if mask & GL_COLOR_BUFFER_BIT is true*/
        void setClearColor(const osg::Vec4& color) { _clearColor=color; }
        
        /** Get the clear color.*/
        const osg::Vec4& getClearColor() const { return _clearColor; }
        

        /** Set the clear accum used in glClearAccum(..). 
          * glClearAcumm is only called if mask & GL_ACCUM_BUFFER_BIT is true*/
        void setClearAccum(const osg::Vec4& color) { _clearAccum=color; }
        
        /** Get the clear accum.*/
        const osg::Vec4& getClearAccum() const { return _clearAccum; }
        

        
        /** Set the clear depth used in glClearDepth(..). Defaults to 1.0
          * glClearDepth is only called if mask & GL_DEPTH_BUFFER_BIT is true*/
        void setClearDepth(const double depth) { _clearDepth=depth; }
        
        /** Get the clear depth.*/
        const double getClearDepth() const { return _clearDepth; }

        
        /** Set the clear stencil value used in glClearStencil(). Defaults to 1.0 
          * glClearStencil is only called if mask & GL_STENCIL_BUFFER_BIT is true*/
        void setClearStencil(const int stencil) { _clearStencil=stencil; }
        
        /** Get the clear color.*/
        const int getClearStencil() const { return _clearStencil; }

        void setRenderStageLighting(RenderStageLighting* rsl) { _renderStageLighting = rsl; }

        RenderStageLighting* getRenderStageLighting() const
        {
            if (!_renderStageLighting.valid()) _renderStageLighting = new RenderStageLighting;
            return _renderStageLighting.get();
        }

        virtual void addPositionedAttribute(osg::Matrix* matrix,const osg::StateAttribute* attr)
        {
            getRenderStageLighting()->addPositionedAttribute(matrix,attr);
        }
        
        virtual void draw(osg::State& state,RenderLeaf*& previous);

        void addToDependencyList(RenderStage* rs);

        /** extract stats for current draw list. */
        bool getStats(osg::Statistics* primStats); 
        
    public:
        
        typedef std::vector< osg::ref_ptr<RenderStage> > DependencyList;

        bool                                _stageDrawnThisFrame;
        DependencyList                      _dependencyList;

        // viewport x,y,width,height.
        osg::ref_ptr<osg::Viewport>         _viewport;
        
        GLbitfield                          _clearMask;
        osg::ref_ptr<osg::ColorMask>        _colorMask;
        osg::Vec4                           _clearColor;
        osg::Vec4                           _clearAccum;
        double                              _clearDepth;
        int                                 _clearStencil;

        mutable osg::ref_ptr<RenderStageLighting>   _renderStageLighting;
        
    protected:
    
        virtual ~RenderStage();

};

